#include "userdict.h"
#include "pinyinhandler.h"
#include "configmanager.h"
#include "encryptutil.h"
#include "IUserDict.h"
#include "OpenCCUtil.h"

#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>
#include <QFile>
#include <QDir>
#include <QNetworkInterface>
#include <QHostInfo>
#include <QTextStream>
#include <QRegularExpression>
#include <openssl/evp.h>

// static 成员变量
UserDict* UserDict::m_instance = nullptr;
QMutex UserDict::m_instanceMutex;
const QByteArray UserDict::FIXED_IV = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");  // 16字节固定IV

// 构造函数：明确初始化QObject基类（解决歧义）
UserDict::UserDict(QObject *parent) : QObject(parent)
{
    m_encryptKey = EncryptUtil::generateKey();
    ConfigManager* config = ConfigManager::getInstance();
    m_encryptEnabled = config->isUserWordEncrypted();
    m_mySQLTable = config->getValue(InputMethodGroup, "MySQLTable", "user_words").toString();

    m_openccUtil = OpenCCUtil::getInstance();
    if (!m_openccUtil->isInitialized())     qWarning() << "[UserDict] OpenCCUtil未初始化，简繁同步功能不可用";

    QObject::connect(m_openccUtil, &OpenCCUtil::initFailed, this, [this](const QString& err) {
        qWarning() << "[UserDict] OpenCCUtil初始化失败，简繁同步不可用：" << err;
    });
}

UserDict::~UserDict()
{
	QMutexLocker locker(&m_dbMutex);
    if (m_db.isOpen()) m_db.close();
    
    if (m_pinyinGenerator) {
		auto internalAdapter = dynamic_cast<PinyinHandlerAdapter*>(m_pinyinGenerator);
        delete m_pinyinGenerator;
        m_pinyinGenerator = nullptr;
    }
    qInfo() << "[UserDict] 析构完成，已关闭数据库连接";
}

UserDict *UserDict::getInstance(QObject *parent)
{
	// 双重检查锁定（线程安全）
    if (!m_instance) {
        QMutexLocker locker(&m_instanceMutex);
        if (!m_instance) {
            m_instance = new UserDict(parent);
            // 初始化拼音生成器（适配PinyinHandler）
            PinyinHandler* handler = new PinyinHandler();
            m_instance->setPinyinGenerator(new PinyinHandlerAdapter(handler));
            // 初始化MySQL（从ConfigManager读取配置）
            if (!m_instance->initDatabase()) {
                qCritical() << "[UserDict] 单例初始化失败：MySQL连接失败";
                delete m_instance;
                m_instance = nullptr;
            }
        }
    }
	// 检查实例是否有效
    if (!m_instance) {
        qCritical() << "[UserDict] 单例获取失败：实例未初始化";
    }
    return m_instance;
}

bool UserDict::initDatabase()
{
	// 先关闭现有连接（重置状态）
    QMutexLocker locker(&m_dbMutex);
    if (m_db.isOpen()) m_db.close();
    m_isConnected = false;

    // 检查MySQL驱动
    if (!QSqlDatabase::isDriverAvailable("QMYSQL")) {
        QString err = "[UserDict] MySQL驱动不可用，请安装Qt MySQL插件（如libqsqlmysql.so/libqsqlmysql.dll）";
        qWarning() << err;
        emit databaseError(err);
        return false;
    }

    // 从ConfigManager读取MySQL配置
    ConfigManager* config = ConfigManager::getInstance();
    QString host = config->getMySQLHost();
    int port = config->getMySQLPort();
    QString dbName = config->getMySQLDbName();
    QString user = config->getMySQLUser();
    QString password = config->getMySQLPassword();

    // 创建MySQL连接（用唯一连接名，避免冲突）
    m_db = QSqlDatabase::addDatabase("QMYSQL", "UserDict_MySQL_Connection");
    m_db.setHostName(host);
    m_db.setPort(port);
    m_db.setDatabaseName(dbName);
    m_db.setUserName(user);
    m_db.setPassword(password);

    // 连接数据库并创建表
    if (!m_db.open()) {
        QString err = "[UserDict] MySQL连接失败：" + m_db.lastError().text() +  "（检查：host=" + host + ", port=" + QString::number(port) + ", db=" + dbName + "）";
        qWarning() << err;
        emit databaseError(err);
        return false;
    }

    // 创建用户词库表（表结构适配加密存储）
    if (!createTables()) {
        m_db.close();
        emit databaseError("[UserDict] 初始化用户词库表失败");
        return false;
    }

    m_isConnected = true;
    qInfo() << "[UserDict] MySQL连接成功：" << host << ":" << port << "/" << dbName << "（表：" << m_mySQLTable << "）";
    return true;
}

bool UserDict::addWord(const QString &word, const QString &pinyin, int frequency)
{
	QMutexLocker locker(&m_dbMutex);
    if (!m_isConnected || word.isEmpty() || frequency <= 0) {
        emit databaseError("[UserDict] 添加用户词失败：数据库未连接或参数无效");
        return false;
    }

	// 自动生成拼音（若未传）
	QString finalPinyin = pinyin.isEmpty() ? m_pinyinGenerator->generatePinyin(word) : pinyin;
    if (finalPinyin.isEmpty()) {
        emit databaseError("[UserDict] 拼音生成失败，无法添加词语：" + word);
        return false;
    }

    // 生成繁体
    QString twWord = generateTraditionalWord(word);
    if (twWord.isEmpty()) {
        emit databaseError("[UserDict] 添加用户词失败：繁体词生成失败（词语：" + word + "）");
        return false;
    }

	// 检查加密结果是否有效
    QByteArray encryptedCnWord = encryptField(word);
    QByteArray encryptedTwWord = encryptField(twWord);
    QByteArray encryptedPinyin = encryptField(finalPinyin);
    if (encryptedCnWord.isEmpty() || encryptedTwWord.isEmpty() || encryptedPinyin.isEmpty()) {
        emit databaseError("[UserDict] 添加用户词失败：字段加密失败（词语：" + word + "）");
        return false;
    }

	// 执行查询  预处理SQL（防注入）
	QSqlQuery query(m_db);
    query.prepare(QString(R"(
        INSERT INTO %1 (cn_word, tw_word, pinyin, frequency, encrypt_flag)
        VALUES (:cn_word, :tw_word, :pinyin, :frequency, :encrypt_flag)
        ON DUPLICATE KEY UPDATE 
            frequency = frequency + :frequency,
            tw_word = :tw_word,  -- 重复时更新繁体词（避免简繁不同步）
            update_time = CURRENT_TIMESTAMP;
    )").arg(m_mySQLTable));

    // 绑定参数
    query.bindValue(":cn_word", encryptedCnWord);
    query.bindValue(":tw_word", encryptedTwWord);
    query.bindValue(":pinyin", encryptedPinyin);
    query.bindValue(":frequency", frequency);
    query.bindValue(":encrypt_flag", m_encryptEnabled ? 1 : 0);  // 绑定加密标识

	if (!query.exec()) {
		// 发信号了
		QString err = "[UserDict] 添加词语失败：" + query.lastError().text() + "（词语：" + word + "）";
        qWarning() << err;
        emit databaseError(err);
        return false;
	}

	// 发送简繁同步完成信号
    emit wordSynced(word, twWord);
    // 发送词典变更信号（通知UI刷新）
    emit dictChanged();
    qInfo() << "[UserDict] 添加/更新用户词成功：" << word << "（繁体：" << twWord << "，词频：" << frequency << "）";
    return true;
}

bool UserDict::removeWord(const QString &word)
{
	if (!m_isConnected || word.isEmpty()) return false;

    QByteArray encryptedWord = encryptField(word);
    QSqlQuery query(m_db);
    query.prepare(QString("DELETE FROM %1 WHERE word = :word;").arg(m_mySQLTable));
    query.bindValue(":word", encryptedWord);

    if (!query.exec()) {
        QString err = "[UserDict] 删除词语失败：" + query.lastError().text() + "（词语：" + word + "）";
        qWarning() << err;
        emit databaseError(err);
        return false;
    }

    if (query.numRowsAffected() > 0) {
        emit dictChanged();
        qDebug() << "[UserDict] 删除用户词成功：" << word;
        return true;
    }

    emit databaseError("[UserDict] 删除失败：词语不存在（" + word + "）");
    return false;
}

bool UserDict::updateFrequency(const QString &word, int increment)
{
	if (!m_isConnected || word.isEmpty() || increment <= 0) return false;

    QByteArray encryptedWord = encryptField(word);
    QSqlQuery query(m_db);
    query.prepare(QString(R"(
        UPDATE %1 
        SET frequency = frequency + :increment, update_time = CURRENT_TIMESTAMP 
        WHERE word = :word;
    )").arg(m_mySQLTable));

    query.bindValue(":word", encryptedWord);
    query.bindValue(":increment", increment);

    if (!query.exec()) {
        QString err = "[UserDict] 更新词频失败：" + query.lastError().text() + "（词语：" + word + "）";
        qWarning() << err;
        emit databaseError(err);
        return false;
    }

    if (query.numRowsAffected() > 0) {
        emit dictChanged();
        qDebug() << "[UserDict] 更新词频成功：" << word << "（增量：" << increment << "）";
        return true;
    }

    emit databaseError("[UserDict] 更新词频失败：词语不存在（" + word + "）");
    return false;
}

QVector<PinyinCandidate> UserDict::queryWords(const QString &pinyin)
{
	QVector<PinyinCandidate> candidates;
    QMutexLocker locker(&m_dbMutex);
    if (!m_isConnected || pinyin.isEmpty()) return candidates;

    // 拼音加密（使用固定IV，确保前缀一致性）
    QByteArray encryptedPinyin = encryptField(pinyin);
    // 拼接通配符（在加密后的数据上添加%，利用MySQL对二进制的LIKE支持）
    encryptedPinyin += '%';

    QSqlQuery query(m_db);
    query.prepare(QString(R"(
        SELECT cn_word, tw_word, pinyin, frequency, encrypt_flag
        FROM %1 
        WHERE pinyin LIKE :pinyin 
        ORDER BY frequency DESC 
        LIMIT 20;  -- 限制返回数量，避免性能问题
    )").arg(m_mySQLTable));
    query.bindValue(":pinyin", encryptedPinyin);
    if (!query.exec()) {
        QString err = "[UserDict] 查询用户词失败：" + query.lastError().text() + "（拼音：" + pinyin + "）";
        qWarning() << err;
        emit databaseError(err);
        return candidates;
    }

    // 解密并构造候选词
    while (query.next()) {
        // 读取加密字段
        QByteArray encryptedCn = query.value("cn_word").toByteArray();
        QByteArray encryptedTw = query.value("tw_word").toByteArray();
        QByteArray encryptedPin = query.value("pinyin").toByteArray();
        int frequency = query.value("frequency").toInt();
        int encryptFlag = query.value("encrypt_flag").toInt();

        // 根据加密标识解密
        QString cnWord = (encryptFlag == 1) ? decryptField(encryptedCn) : QString::fromUtf8(encryptedCn);
        QString twWord = (encryptFlag == 1) ? decryptField(encryptedTw) : QString::fromUtf8(encryptedTw);
        QString decryptedPin = (encryptFlag == 1) ? decryptField(encryptedPin) : QString::fromUtf8(encryptedPin);

        // 校验字段有效性，添加简体词候选
        if (!cnWord.isEmpty() && !decryptedPin.isEmpty()) {
            candidates.append({cnWord, frequency, decryptedPin, true});
        }
        // 校验字段有效性，添加繁体词候选（标记为用户词）
        if (!twWord.isEmpty() && !decryptedPin.isEmpty() && twWord != cnWord) {
            candidates.append({twWord, frequency, decryptedPin, true});
        }
    }

    qInfo() << "[UserDict] 查询拼音：" << pinyin << "，匹配用户词数量：" << candidates.size();
    return candidates;
}

bool UserDict::exportDict(const QString &exportPath, bool encrypt)  
{
    if (!m_isConnected) {
        emit databaseError("[UserDict] 导出失败：MySQL未连接");
        return false;
    }

    QFile file(exportPath);
    // 使用QIODevice::Text模式会自动处理换行符转换（\n -> 系统换行符）
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QString err = "[UserDict] 导出文件打开失败：" + file.errorString();
        qWarning() << err;
        emit databaseError(err);
        return false;
    }

    QTextStream out(&file);
    out.setEncoding(QStringConverter::Utf8);  // 明确UTF-8编码，确保多语言兼容性

    // 写入CSV表头（使用制表符分隔，符合常见词典导出格式）
    out << "词语\t拼音\t词频\n";

    QSqlQuery query(m_db);
    // 查询时包含加密标识，用于精准解密（兼容混合加密状态的记录）
    QString exportSql = QString("SELECT word, pinyin, frequency, encrypt_flag FROM %1 ORDER BY frequency DESC;")
                            .arg(m_mySQLTable);

    if (!query.exec(exportSql)) {
        QString err = "[UserDict] 导出查询失败：" + query.lastError().text();
        qWarning() << err;
        emit databaseError(err);
        file.close();  // 确保文件关闭
        return false;
    }

    int count = 0;
    int skipCount = 0;  // 统计跳过的无效记录
    // CSV字段转义处理：包含特殊字符时用引号包裹，内部引号转义为双引号
    auto escapeCsvField = [](const QString &field) {
        if (field.contains('\t') || field.contains('"') || field.contains('\n') || field.contains('\r')) {
            // 替换双引号为两个双引号，再包裹外层双引号
            QString tmp = field;
            tmp.replace("\"", "\"\"");
            return QString("\"%1\"").arg(tmp);
        }
        return field;
    };

    while (query.next()) {
        // 读取字段值
        QByteArray encryptedWord = query.value("word").toByteArray();
        QByteArray encryptedPinyin = query.value("pinyin").toByteArray();
        int frequency = query.value("frequency").toInt();
        int encryptFlag = query.value("encrypt_flag").toInt();  // 每条记录的加密标识

        // 根据记录自身的加密标识解密（而非全局开关，兼容历史数据）
        QString word = (encryptFlag == 1) ? decryptField(encryptedWord) : QString::fromUtf8(encryptedWord);
        QString pinyin = (encryptFlag == 1) ? decryptField(encryptedPinyin) : QString::fromUtf8(encryptedPinyin);

        // 校验字段有效性
        if (word.isEmpty() || pinyin.isEmpty() || frequency <= 0) {
            qWarning() << "[UserDict] 跳过无效记录：" << word << pinyin << frequency;
            skipCount++;
            continue;
        }

        // 写入转义后的字段
        out << escapeCsvField(word) << "\t"
            << escapeCsvField(pinyin) << "\t"
            << frequency << "\n";

        count++;
    }

    // 确保数据写入磁盘
    out.flush(); // QTextStream::flush() 返回 void，先调用以确保缓冲刷新到 QFile
    if (!file.flush()) {
        QString err = "[UserDict] 写入文件失败：" + file.errorString();
        qWarning() << err;
        emit databaseError(err);
        file.close();
        return false;
    }

    file.close();

    // 输出详细统计信息
    QString log = QString("[UserDict] 导出完成：成功%1条，跳过无效记录%2条（路径：%3）")
                     .arg(count).arg(skipCount).arg(exportPath);
    qInfo() << log;
    emit databaseError(log);  // 通知UI层导出结果

    return count > 0;  // 即使有跳过记录，只要成功导出至少一条就算成功
}

bool UserDict::importDict(const QString &importPath)
{
	if (!m_isConnected) {
        emit databaseError("[UserDict] 导入失败：MySQL未连接");
        return false;
    }

    QFile file(importPath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QString err = "[UserDict] 导入文件打开失败：" + file.errorString();
        emit databaseError(err);
        return false;
    }

    QTextStream in(&file);
    in.setEncoding(QStringConverter::Utf8);
    QString header = in.readLine();  // 跳过表头

    // 开启事务前检查连接状态（防止中途断开）
    if (!m_db.isOpen()) {
        file.close();
        emit databaseError("[UserDict] 导入失败：数据库连接已断开");
        return false;
    }

    // 开启事务
    if (!m_db.transaction()) {
        file.close();
        QString err = "[UserDict] 开启事务失败：" + m_db.lastError().text();
        emit databaseError(err);
        return false;
    }

    int success = 0, fail = 0;
    bool transactionActive = true;  // 标记事务状态

    try {
        while (!in.atEnd()) {
            QString line = in.readLine().trimmed();
            if (line.isEmpty()) continue;

            // CSV解析逻辑（处理带引号的字段）
            QStringList parts;
            bool inQuotes = false;
            QString currentPart;
            for (QChar c : line) {
                if (c == '"') {
                    inQuotes = !inQuotes;
                } else if (c == '\t' && !inQuotes) {
                    parts.append(currentPart);
                    currentPart.clear();
                } else {
                    currentPart.append(c);
                }
            }
            parts.append(currentPart);

            if (parts.size() < 2) {
                fail++;
                continue;
            }

			// 解析字段（处理双引号转义）
            QString word = parts[0].replace("\"\"", "\"");
            QString pinyin = parts[1].replace("\"\"", "\"");
            int freq = 1;
            if (parts.size() >= 3) {
                bool ok = false;
                int parsed = parts[2].toInt(&ok);
                if (ok && parsed > 0) freq = parsed;
            }

            if (addWord(word, pinyin, freq)) {
                success++;
            } else {
                fail++;
            }

            // 检查事务是否意外中断
            if (!m_db.isOpen()) {
                throw QString("数据库连接中断，导入终止");
            }
        }
    } catch (const QString &e) {
        // 捕获解析或数据库异常，强制回滚
        m_db.rollback();
        transactionActive = false;
        file.close();
        QString err = "[UserDict] 导入过程异常：" + e;
        qWarning() << err;
        emit databaseError(err);
        return false;
    }

    // 处理事务提交/回滚
    if (transactionActive) {
        if (success > 0 || fail > 0) {
            if (m_db.commit()) {
                qInfo() << "[UserDict] 导入事务提交成功";
            } else {
                // 提交失败立即回滚，并保留错误信息
                QString errMsg = m_db.lastError().text();
                m_db.rollback();
                file.close();
                qWarning() << "[UserDict] 导入事务提交失败，已回滚：" << errMsg;
                emit databaseError("[UserDict] 导入失败：事务提交失败 - " + errMsg);
                return false;
            }
        } else {
            // 无有效数据，主动回滚
            m_db.rollback();
            qInfo() << "[UserDict] 无有效导入数据，事务已回滚";
        }
    }

    file.close();

    QString log = QString("[UserDict] 导入完成：成功%1条，失败%2条").arg(success).arg(fail);
    qInfo() << log;
    emit databaseError(log);
    if (success > 0) {
        emit dictChanged();  // 只有成功导入时才触发词典变更
        return true;
    } else {
        return false;  // 全失败时返回false
    }
}

int UserDict::getWordCount() const
{
	if (!m_isConnected) return 0;
	// 候选词个数
	QSqlQuery query(m_db);
	// 结果集要有效 然后查个数
	QSqlQuery query(m_db);
    QString countSql = QString("SELECT COUNT(*) FROM %1;").arg(m_mySQLTable);
    if (query.exec(countSql) && query.next()) 
        return query.value(0).toInt();

    qWarning() << "[UserDict] 获取词数失败：" << query.lastError().text();
	return 0;
}

bool UserDict::wordExists(const QString &word)
{
	if (!m_isConnected || word.isEmpty()) return false;
	// 检查存在性
	QByteArray encryptedWord = encryptField(word);
    QSqlQuery query(m_db);
    query.prepare(QString("SELECT id FROM %1 WHERE word = :word;").arg(m_mySQLTable));
    query.bindValue(":word", encryptedWord);
	if (query.exec() && query.next()) 	return true;		// 存在
	return false;
}

void UserDict::setPinyinGenerator(PinyinGeneratorInterface *generator)
{
	// 线程安全处理（避免多线程操作同一指针）
    QMutexLocker locker(&m_dbMutex);

    // 清理旧实例（如果存在且不是默认生成的适配器）
    if (m_pinyinGenerator) {
        // 区分内部创建的适配器和外部注入的实例（避免重复释放）
        auto internalAdapter = dynamic_cast<PinyinHandlerAdapter*>(m_pinyinGenerator);
        if (internalAdapter) {
            // 释放适配器关联的PinyinHandler（内部创建的实例）
            delete internalAdapter;
        } else {
            // 释放外部注入的自定义实现
            delete m_pinyinGenerator;
        }
    }

    // 设置新生成器（允许 nullptr，此时拼音生成会失败，由调用方保证有效性）
    m_pinyinGenerator = generator;

    qInfo() << "[UserDict] 拼音生成器已更新：" << (generator ? "自定义实现" : "空实现");
}

QString UserDict::generateTraditionalWord(const QString &simplifiedWord)
{
	if (!m_openccUtil || !m_openccUtil->isInitialized()) {
        qWarning() << "[UserDict] OpenCCUtil未初始化，无法生成繁体词";
        return "";
    }
    // 调用OpenCCUtil转换为台湾繁体
    return m_openccUtil->convert(simplifiedWord, OpenCCUtil::ConvertDirection::S2T_TW);
}

bool UserDict::syncSimplifiedTraditional(const QString &simplifiedWord, QString &traditionalWord)
{
	traditionalWord = generateTraditionalWord(simplifiedWord);
    if (traditionalWord.isEmpty()) {
        qWarning() << "[UserDict] 简繁同步校验失败：繁体词生成为空（词语：" << simplifiedWord << "）";
        return false;
    }
    // 反向校验：繁体→简体应等于原词（确保转换正确性）
    QString checkSimplified = m_openccUtil->convert(traditionalWord, OpenCCUtil::ConvertDirection::T2S);
    if (checkSimplified != simplifiedWord) {
        qWarning() << "[UserDict] 简繁同步校验失败：" << simplifiedWord << "→" << traditionalWord << "→" << checkSimplified;
        return false;
    }
    return true;
}

bool UserDict::createTables()
{
	// sql 操作
	QSqlQuery query(m_db);

	// mysql 表  word/pinyin用BLOB存储加密后的二进制数据，frequency词频，时间戳跟踪更新
	QString createSql = QString(R"(
        CREATE TABLE IF NOT EXISTS %1 (
            id INT PRIMARY KEY AUTO_INCREMENT,
            cn_word BLOB NOT NULL UNIQUE,  -- 简体词（加密存储）
            tw_word BLOB NOT NULL,         -- 繁体词（加密存储，新增）
            pinyin BLOB NOT NULL,         -- 拼音（加密存储）
            frequency INT NOT NULL DEFAULT 1, -- 词频
            encrypt_flag TINYINT NOT NULL DEFAULT 1, -- 加密标识（1=加密，0=未加密）
            create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    )").arg(m_mySQLTable);

	if (!query.exec(createSql)) {
		QString err = "[UserDict] 创建表失败: " + query.lastError().text();
        qWarning() << err;
        emit databaseError(err);
        return false;
	}

	// 拼音索引
	QString pinyinIndexSql = QString("CREATE INDEX IF NOT EXISTS idx_%1_pinyin ON %1(pinyin);").arg(m_mySQLTable);
    if (!query.exec(pinyinIndexSql)) {
        qWarning() << "[UserDict] 创建拼音索引失败：" << query.lastError().text();
    }
    // 简体索引
    QString cnWordIndexSql = QString("CREATE INDEX IF NOT EXISTS idx_%1_cn_word ON %1(cn_word);").arg(m_mySQLTable);
    if (!query.exec(cnWordIndexSql)) {
        qWarning() << "[UserDict] 创建简体词索引失败：" << query.lastError().text();
    }
	return true;
}

QString UserDict::generatePinyin(const QString &word)
{
	if (!m_pinyinGenerator) {
        qWarning() << "[UserDict] 未设置 PinyinGenerator，无法自动生成拼音";
        return "";
    }

    // 调用 PinyinHandler 生成文本拼音（如"编程"→"bian cheng"）
    QString pinyin = m_pinyinGenerator->generatePinyin(word);
    if (pinyin.isEmpty()) {
        qWarning() << "[UserDict] 拼音生成失败：" << word;
        return "";
    }

    qDebug() << "[UserDict] 自动生成拼音：" << word << "→" << pinyin;
    return pinyin;
}

QByteArray UserDict::encryptField(const QString &text) const
{
	if (!m_encryptEnabled || text.isEmpty()) return text.toUtf8();
    // 简单判断是否为拼音（含空格或纯字母）
    // text 为 const 引用，先拷贝到可变变量再处理空格，并使用 QRegularExpression 检测纯字母拼音
    QString noSpace = text;
    noSpace.remove(' ');
    bool isPinyin = text.contains(' ') || noSpace.contains(QRegularExpression("^[a-zA-ZüÜ]+$"));

    // 区分处理：拼音使用固定IV（支持模糊查询），词语使用随机IV（更高安全性）
    if (isPinyin) {  // 简单判断是否为拼音
        // 拼音加密：固定IV（确定性加密）
        QByteArray padded = EncryptUtil::addPkcs7Padding(text.toUtf8(), 16);
        EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
        EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, 
                          reinterpret_cast<const unsigned char*>(m_encryptKey.data()),
                          reinterpret_cast<const unsigned char*>(FIXED_IV.data()));

        // 执行加密
        int outLen = 0, totalLen = 0;
        QByteArray encrypted(padded.size() + 16, 0);
        EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(encrypted.data()), &outLen,
                         reinterpret_cast<const unsigned char*>(padded.data()), padded.size());
        totalLen += outLen;
        EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(encrypted.data()) + totalLen, &outLen);
        totalLen += outLen;
        encrypted.truncate(totalLen);
        EVP_CIPHER_CTX_free(ctx);
        return encrypted;  // 无需拼接IV（固定IV可硬编码）
    } else {
        // 词语加密：随机IV（原有逻辑）
        return EncryptUtil::encryptString(text, m_encryptKey);
    }
}

QString UserDict::decryptField(const QByteArray &encryptedData) const
{
	if (!m_encryptEnabled || encryptedData.isEmpty()) return QString::fromUtf8(encryptedData);

    // 拼音解密：使用固定IV（无前置IV，直接解密）
    QByteArray iv = FIXED_IV;
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr,
                      reinterpret_cast<const unsigned char*>(m_encryptKey.data()),
                      reinterpret_cast<const unsigned char*>(iv.data()));
    // 执行解密（简化代码）
    int outLen = 0, totalLen = 0;
    QByteArray decryptedData(encryptedData.size() + 16, 0);
    EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(decryptedData.data()), &outLen,
                     reinterpret_cast<const unsigned char*>(encryptedData.data()), encryptedData.size());
    totalLen += outLen;
    EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(decryptedData.data()) + totalLen, &outLen);
    totalLen += outLen;
    decryptedData.truncate(totalLen);
    EVP_CIPHER_CTX_free(ctx);
    return QString::fromUtf8(EncryptUtil::removePkcs7Padding(decryptedData));
}

QString UserDict::getDeviceUniqueId() const
{
	// 收集多维度设备特征（兼顾唯一性和跨平台性）
    QStringList uniqueFactors;

    // 系统唯一标识（Qt跨平台接口，优先使用）
    QByteArray machineId = QSysInfo::machineUniqueId();
    if (!machineId.isEmpty()) {
        uniqueFactors << machineId.toHex();
    }

    // 硬件相关信息（增强唯一性）
    uniqueFactors << QSysInfo::currentCpuArchitecture();
    {
        // 对 kernelVersion 使用可用的哈希函数生成稳定表示（QString 没有 hash() 成员）
        QByteArray kernelHash = QCryptographicHash::hash(QSysInfo::kernelVersion().toUtf8(), QCryptographicHash::Sha256);
        uniqueFactors << kernelHash.toHex();
    }

    // 网络标识（主机名+MAC地址哈希，避免直接暴露硬件地址）
    uniqueFactors << QHostInfo::localHostName();
    // 计算MAC地址哈希（不直接存储原始MAC，保护隐私）
    foreach (const QNetworkInterface &iface, QNetworkInterface::allInterfaces()) {
        if (iface.flags().testFlag(QNetworkInterface::IsUp) && 
            !iface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
            uniqueFactors << QString(iface.hardwareAddress().toUtf8().toHex());
        }
    }

    // 组合信息并生成SHA256哈希（比MD5更安全，适合密钥相关场景）
    const QString combined = uniqueFactors.join("|");
    QByteArray hash = QCryptographicHash::hash(combined.toUtf8(), QCryptographicHash::Sha256);

    // 返回64位十六进制字符串（确保密钥生成的熵足够）
    return hash.toHex();
}

QString UserDict::escapeCsvField(const QString &field) const
{
	// 静态正则表达式（仅初始化一次，提升性能）
    static const QRegularExpression needEscapeRegex(QLatin1String("[,\t\"\\r\\n]"));

    // 无需转义的情况直接返回
    if (!needEscapeRegex.match(field).hasMatch()) {
        return field;
    }

    // 转义规则：双引号替换为两个双引号，整体用双引号包裹
    QString escaped = field;
    escaped.replace(QLatin1String("\""), QLatin1String("\"\""));
    return QLatin1String("\"") + escaped + QLatin1String("\"");
}
